package com.dco.dcowebhook.controller;

import com.dco.dcowebhook.model.WebhookPayload;
import com.dco.dcowebhook.service.DcoService;
import com.dco.dcowebhook.service.EmailService;
import com.dco.dcowebhook.service.DataService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.*;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@RestController
@RequestMapping("/webhook")
public class WebhookController {

    private static final Logger logger = LoggerFactory.getLogger(WebhookController.class);

    @Value("${WEBHOOK_SECRET:}")
    private String webhookSecret;

    @Autowired
    private DcoService dcoService;

    @Autowired
    private EmailService emailService;

    @Autowired
    private DataService dataService;

    @PostMapping
    public ResponseEntity<Map<String, Object>> handleWebhook(
            HttpServletRequest request,
            @RequestBody(required = false) String payload
    ) {
        logger.debug("收到 Webhook 请求。");

        // 获取请求头中的签名
        String signature = request.getHeader("X-Hub-Signature");
        logger.debug("Webhook 签名: {}", signature);

        // 验证签名
        if (!dcoService.verifySignature(signature, webhookSecret)) {
            logger.warn("Webhook 签名验证失败。");
            Map<String, String> response = new HashMap<>();
            response.put("message", "Unauthorized");
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Collections.unmodifiableMap(response));
        }

        // 获取事件类型
        String event = request.getHeader("X-AtomGit-Event");
        logger.info("处理事件类型: {}", event);

        // 只处理 Push Hook 事件
        if (!"push".equals(event)) {
            logger.info("事件类型不处理。");
            Map<String, String> response = new HashMap<>();
            response.put("message", "Event not handled");
            return ResponseEntity.ok(Collections.unmodifiableMap(response));
        }

        // 解析 JSON 负载
        ObjectMapper mapper = new ObjectMapper();
        WebhookPayload data;
        try {
            data = mapper.readValue(payload, WebhookPayload.class);
            logger.debug("Webhook Payload: {}", payload);
        } catch (Exception e) {
            logger.error("解析 Webhook 负载失败: {}", e.getMessage());
            Map<String, String> response = new HashMap<>();
            response.put("message", "Invalid payload");
            return ResponseEntity.badRequest().body(Collections.unmodifiableMap(response));
        }

        // 获取推送信息
        String owner = data.getRepository().getOwner().getName();
        String repo = data.getRepository().getName();
        List<WebhookPayload.Commit> commits = data.getCommits();
        String pusher = commits.get(0).getAuthor().getName();
        String ref = data.getRef();
        String before = data.getBefore();
        String after = data.getAfter();

        if (owner == null || owner.isEmpty() || repo == null || repo.isEmpty() || commits == null) {
            logger.error("缺少必要的仓库或提交信息。");
            Map<String, String> response = new HashMap<>();
            response.put("message", "Missing information");
            return ResponseEntity.badRequest().body(Collections.unmodifiableMap(response));
        }

        logger.info("处理仓库: {}/{}, Pusher: {}, Ref: {}", owner, repo, pusher, ref);

        List<WebhookPayload.InvalidCommit> invalidCommits = new ArrayList<>();

        for (WebhookPayload.Commit commit : commits) {
            String message = commit.getMessage();
            String sha = commit.getId();
            String author = commit.getAuthor().getName();
            String url = commit.getUrl();

            logger.debug("验证提交 {} 的 DCO 签名。", sha);
            if (!dcoService.validateDco(message)) {
                logger.info("提交 {} 由 {} 创建，未通过 DCO 验证。", sha, author);
                invalidCommits.add(new WebhookPayload.InvalidCommit(sha, author, message, url));
            } else {
                logger.debug("提交 {} 通过 DCO 验证。", sha);
            }
        }

        // 插入 Webhook 负载数据
        dataService.insertWebhookData(data);
        logger.info("Webhook 数据已插入数据库。");

        if (!invalidCommits.isEmpty()) {
            String subject = String.format("DCO 验证失败 - 仓库 %s/%s 的新提交", owner, repo);
            StringBuilder body = new StringBuilder("以下提交缺少有效的 `Signed-off-by` 行，请在每次提交时使用 `git commit -s` 添加签名：\n\n");
            for (WebhookPayload.InvalidCommit commit : invalidCommits) {
                body.append(String.format("- **Commit SHA**: %s\n", commit.getSha()));
                body.append(String.format("  - **作者**: %s\n", commit.getAuthor()));
                body.append(String.format("  - **消息**: %s\n", commit.getMessage()));
                body.append(String.format("  - **链接**: %s\n\n", commit.getUrl()));
            }

            // 插入未通过 DCO 验证的提交数据
            dataService.insertInvalidCommits(invalidCommits);

            // 发送邮件通知
            emailService.sendEmailAsync(subject, body.toString());

            logger.info("发现 {} 个未通过 DCO 验证的提交，已发送邮件通知。", invalidCommits.size());
        } else {
            logger.info("所有提交均通过 DCO 验证。");
        }

        Map<String, String> response = new HashMap<>();
        response.put("message", "Processed");
        return ResponseEntity.ok(Collections.unmodifiableMap(response));
    }
}
